home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
textool
/
sunstuff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
38KB
|
1,621 lines
/*
* This file contains the Sun specific bits of TeXtool, a TeX previewer
* derived from the texview posted on the network about spring 86, which
* in turn was derived from an earlier version and so on right back to
* a version for the BBN Bitgraph.
*
* This stuff deals with all SunView related things and calls things
* in the dvistuff file to do the DVI file and font file stuff, which
* in turn calls things in here like SetChar and SetRule to drive the
* screen.
*/
/*
* Version 2.1 of 30 Oct 87 -- first real outside release
*
* -> V2.2, 27 Nov 87 -- fixed bug where .dvi file was opened twice,
* once from FrameDoneProc() and once by the WIN_REPAINT
* case in CanvasEventProc(). This ran us out of fds.
* -> V2.3, 29 Mar 88 -- fixed sloppy code in skip_specials() in
pkstuff.c
* that caused specials
to be missed and treated as chars.
*/
/* include the various global #defines */
#include "defs.h"
/* now some definitions for the menu items */
/*
* NOTE: The menu items must be in the positions in the menu given by
* these values. This is not done automatically!
*/
#define M_NULL 0
#define M_RESTART 1
#define M_NEWPAGE 2
#define M_NEWFILE 3
#define M_CD 4
#define M_TEX 5
#define M_LATEX 6
#define M_EDIT 7
#define M_SHELL 8
#define SM_TOGGLE_P 0x11
#define SM_TOGGLE_BIGP 0x12
#define SM_TOGGLE_B 0x13
#define SM_TOGGLE_M 0x14
#define DM_TOGGLE_D 0x21
#define DM_TOGGLE_X 0x22
#define DM_SHOW_FD 0x23
#define DM_SHOW_PXL_CACHE 0x24
/* now some Sun include files */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <stdio.h>
#include <pwd.h>
#include <pixrect/pixrect_hs.h>
#include <suntool/sunview.h>
#include <suntool/icon_load.h>
#include <suntool/canvas.h>
#include <suntool/scrollbar.h>
#include <suntool/panel.h>
#include <suntool/tty.h>
/* general external procedures */
char *getenv();
char *index();
char *rindex();
char *sprintf();
char *strcpy();
char *strcat();
int strlen();
char *getwd();
/* procedures from dvistuff */
extern void CloseDviFile();
extern void DoPage();
extern Boolean DviFileChanged();
extern void FreeFontStorage();
extern void OpenDviFile();
#ifdef DEBUG
extern void ShowPxlFd();
extern void ShowPxlCache();
#endif
/* procedures from pxlstuff or pkstuff */
extern void LoadAChar();
/* procedures in this file */
void BatchEnd();
void BatchStart();
void CanvasEventProc();
Notify_value CanvasInterposer();
void CheckFiles();
void ErrorEventProc();
char *ExpandTilde();
void Fatal();
void FrameDoneProc();
void InitWindows();
void MenuCd();
void MenuEdit();
Menu MenuGenerate();
void MenuLatex();
void MenuNewFile();
void MenuNewPage();
void MenuRestart();
void MenuShell();
void MenuShortPage();
void MenuTex();
void MenuToggleFlag();
void ProcessPage();
void RestartDviFile();
void SetBop();
void SetChar();
void SetFrameLabel();
void SetPageMenu();
void SetRule();
Menu ShiftMenuGenerate();
void SplitFilename();
void TextInputProc();
void Warning();
#ifdef DEBUG
Menu DebugMenuGenerate();
void ShowFd();
#endif
/* now include real global variables needed by both files */
#define _DEFINE
#include "globals.h"
/* now the "globals" only needed here */
static char progname[STRSIZE]; /* program name */
static char ttyinbuf[STRSIZE]; /* for input to ttysubwindow */
static char dirbuf[STRSIZE]; /* current working dir. */
static char framelabelbuf[STRSIZE]; /* for frame label */
static char curarea[STRSIZE]; /* current file area */
static char curext[STRSIZE]; /* current file extension */
static char curname[STRSIZE]; /* current file name */
static char textinputbuffer[STRSIZE]; /* for copying text panel item value */
static char dviname[STRSIZE]; /* current complete DVI filename */
static short textinput_state;
/* display related stuff */
static int hh; /* current horizontal position in pixels */
static int vv; /* current vertical position in pixels */
static int current_page; /* pagepointers index for current page */
static int xcanvasoffset = RESOLUTION; /* 1 inch offset to match TeX's */
static int ycanvasoffset = RESOLUTION; /* 1 inch margin on paper */
static Boolean keyscroll; /* bodge to say h,j,k or l typed */
/* SunView defs */
Frame frame;
Icon icon;
Canvas canvas;
Pixwin *pw;
Scrollbar vsb, hsb;
Cursor canvas_cursor;
Menu menu, tenpagemenu, shiftmenu;
Menu_item shortpageitem, longpageitem;
Frame ttyframe;
Tty ttysubwindow;
Frame errorframe;
Panel errorpanel;
Panel_item errorheader, errormessage;
Panel_item textinput;
#ifdef DEBUG
Menu debugmenu;
#endif
/* now the real code */
main(argc, argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
int c;
strcpy(progname, argv[0]);
/* initialse some globals */
Debug = FALSE;
ExtraDebug = FALSE;
PreLoad = FALSE;
BigPreLoad = FALSE;
Batching = TRUE;
main_state = SB_INITIAL;
Mflag = FALSE;
pagepointers = NULL; /* we haven't malloc'd them yet */
InitWindows(&argc, argv); /* setup windows and consume -W args */
current_page = 0; /* start at the beginning */
/* get enviroment variables for different PXL directories */
if ((PXLpath=getenv("PXLPATH")) == NULL)
PXLpath = PXLFONTAREA;
if ((PKpath=getenv("PKPATH")) == NULL)
PKpath = PKFONTAREA;
while ((c = getopt(argc, argv, "dxpPbm:")) != EOF)
switch(c) {
case 'd': /* d selects Debug output */
Debug = TRUE;
break;
case 'x': /* extra debug info for pxl files */
ExtraDebug = TRUE;
break;
case 'p': /* p enables font pre-loading */
PreLoad = TRUE;
break;
case 'P': /* P enables char pixrect pre-loading */
BigPreLoad = TRUE;
break;
case 'b': /* turn batching off for slowness */
Batching = FALSE;
break;
case 'm': /* specify mag to override that in DVI file */
Mflag = TRUE;
user_mag = atoi(optarg);
break;
case '?':
default:
fprintf(stderr,
"usage: textool [-pPb] [-m <mag>] [+n] file\n");
exit(1);
}
if ((optind < argc) && (argv[optind][0] == '+'))
/* we have starting page number */
sscanf(&argv[optind][1], "%d", ¤t_page);
if (optind >= argc) {
main_state = SB_NOFILE; /* cancel SB_INITIAL status */
SplitFilename("<no_file>"); /* _ as icon labels don't like space */
}
else
SplitFilename(argv[optind]);
SetFrameLabel();
#ifdef DEBUG
if (Debug) fprintf(stderr,"going into window_main_loop()\n");
#endif
window_main_loop(frame);
}
/*-->InitWindows*/
void
InitWindows(argcptr, argv) /* initialize SunView stuff */
int *argcptr;
char **argv;
{
Pixrect *pr1;
char error[IL_ERRORMSG_SIZE];
int i;
pr1 = icon_load_mpr("/u/tex/textool/textool.icon", error);
if (pr1 == NULL) /* couldn't load icon */
fprintf(stderr, "%s\n", error);
/* not Fatal() as windows are not yet active */
icon = icon_create(ICON_IMAGE, pr1,
0);
frame = window_create(0,FRAME,
WIN_WIDTH, 900,
WIN_HEIGHT, 900,
WIN_X, 100,
WIN_Y, 0,
WIN_SHOW, FALSE,
FRAME_LABEL, "TeXtool",
FRAME_ICON, icon,
FRAME_ARGC_PTR_ARGV, argcptr, argv,
0);
vsb = scrollbar_create(SCROLL_LINE_HEIGHT, 20,
SCROLL_ADVANCED_MODE, TRUE,
0);
hsb = scrollbar_create(SCROLL_LINE_HEIGHT, 20,
SCROLL_ADVANCED_MODE, TRUE,
0);
canvas = window_create(frame,CANVAS,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_AUTO_EXPAND, FALSE,
CANVAS_WIDTH, (17 * RESOLUTION)/2, /* 8.5in */
CANVAS_HEIGHT, 12 * RESOLUTION, /* 12in */
WIN_VERTICAL_SCROLLBAR, vsb,
WIN_HORIZONTAL_SCROLLBAR, hsb,
WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS,
WIN_EVENT_PROC, CanvasEventProc,
0);
pw = canvas_pixwin(canvas);
/* interpose before canvas for pageing */
(void)notify_interpose_event_func(canvas, CanvasInterposer, NOTIFY_SAFE);
scrollbar_scroll_to(hsb, (long)RESOLUTION/2);
scrollbar_scroll_to(vsb, (long)RESOLUTION);
/* now make the menu for canvas */
tenpagemenu = menu_create(MENU_ACTION_PROC, MenuShortPage, 0);
menu_set(tenpagemenu,
MENU_STRING_ITEM, "1", 1,
MENU_STRING_ITEM, "2", 2,
MENU_STRING_ITEM, "3", 3,
MENU_STRING_ITEM, "4", 4,
MENU_STRING_ITEM, "5", 5,
MENU_STRING_ITEM, "6", 6,
MENU_STRING_ITEM, "7", 7,
MENU_STRING_ITEM, "8", 8,
MENU_STRING_ITEM, "9", 9,
MENU_STRING_ITEM, "10", 10,
0);
shortpageitem = menu_create_item(MENU_PULLRIGHT_ITEM, "go to page",
tenpagemenu, 0);
longpageitem = menu_create_item(MENU_ACTION_ITEM, "go to page",
MenuNewPage, 0);
menu = menu_create(MENU_GEN_PROC, MenuGenerate,
MENU_ITEM,
MENU_ACTION_ITEM, "restart DVI file", MenuRestart,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "new file", MenuNewFile,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "change directory", MenuCd,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "run tex", MenuTex,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "run latex", MenuLatex,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "edit .tex file", MenuEdit,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "shell", MenuShell,
0,0);
menu_set(menu, MENU_INSERT, 1, shortpageitem, 0);
/* now a second menu for shift-right button */
shiftmenu = menu_create(MENU_GEN_PROC, ShiftMenuGenerate,
MENU_ITEM,
MENU_ACTION_PROC, MenuToggleFlag,
MENU_VALUE, SM_TOGGLE_P,
0,
MENU_ITEM,
MENU_ACTION_PROC, MenuToggleFlag,
MENU_VALUE, SM_TOGGLE_BIGP,
0,
MENU_ITEM,
MENU_ACTION_PROC, MenuToggleFlag,
MENU_VALUE, SM_TOGGLE_B,
0,
MENU_ITEM,
MENU_ACTION_PROC, MenuToggleFlag,
MENU_VALUE, SM_TOGGLE_M,
0,0);
#ifdef DEBUG
/* now a debug menu for the meta key */
debugmenu = menu_create(MENU_GEN_PROC, DebugMenuGenerate,
MENU_ITEM,
MENU_ACTION_PROC, MenuToggleFlag,
MENU_VALUE, DM_TOGGLE_D,
0,
MENU_ITEM,
MENU_ACTION_PROC, MenuToggleFlag,
MENU_VALUE, DM_TOGGLE_X,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "show fd", ShowFd,
MENU_VALUE, DM_SHOW_FD,
0,
MENU_ITEM,
MENU_ACTION_ITEM, "show PXL cache", ShowPxlCache,
MENU_VALUE, DM_SHOW_PXL_CACHE,
0,0);
#endif DEBUG
/* now create a frame and panel for errors */
errorframe = window_create(frame, FRAME,
FRAME_NO_CONFIRM, TRUE,
WIN_SHOW, FALSE,
WIN_COLUMNS, 80,
WIN_ROWS, 2,
WIN_X, 100,
WIN_Y, 100,
0);
errorpanel = window_create(errorframe, PANEL,
PANEL_BACKGROUND_PROC, ErrorEventProc,
PANEL_EVENT_PROC, ErrorEventProc,
0);
errorheader = panel_create_item(errorpanel, PANEL_MESSAGE,
PANEL_LABEL_STRING, "TeXtool Warning:",
0);
errormessage = panel_create_item(errorpanel, PANEL_MESSAGE,
PANEL_LABEL_STRING, "dummy message",
0);
textinput = panel_create_item(errorpanel, PANEL_TEXT,
PANEL_LABEL_STRING, "Magnification:",
PANEL_ITEM_Y, ATTR_ROW(1),
PANEL_ITEM_X, ATTR_COL(0),
PANEL_SHOW_ITEM, FALSE,
PANEL_VALUE_DISPLAY_LENGTH, 40,
PANEL_NOTIFY_PROC, TextInputProc,
0);
window_fit(errorpanel);
window_fit(errorframe);
/* create shell window for TeX, etc */
ttyframe = window_create(frame, FRAME,
FRAME_LABEL, "TeXtool Shell",
FRAME_SHOW_LABEL, TRUE,
FRAME_NO_CONFIRM, TRUE,
FRAME_DONE_PROC, FrameDoneProc,
WIN_X, 25,
WIN_Y, 25,
WIN_SHOW, FALSE,
0);
ttysubwindow = window_create(ttyframe, TTY,
0);
}
/*-->SetFrameLabel*/
void
SetFrameLabel()
{
if (pagepointers == NULL)
sprintf(framelabelbuf,
"TeXtool: Directory: %s File: %s%s%s",
getwd(dirbuf), curarea, curname, curext);
else
sprintf(framelabelbuf,
"TeXtool: Directory: %s File: %s%s%s \"Page\": %d \\count0: %d",
getwd(dirbuf), curarea, curname, curext,
current_page+1, pagepointers[current_page].count_0);
window_set(frame, FRAME_LABEL, framelabelbuf, 0);
}
/*
* Now two procs to deal with canvas input.
* CanvasInterposer is called first and filters out
* the vertical scroll page requests, turning them into
* calls of ProcessPage.
* CanvasEventProc handles all other input cases.
*/
/*-->CanvasInterposer*/
Notify_value
CanvasInterposer(object, event, arg, type)
Canvas object;
Event *event;
Notify_arg arg;
Notify_event_type type;
{
Scroll_motion motion;
Notify_value retval;
#ifdef DEBUG
if (Debug) fprintf(stderr,"Interposer called (%d) - ", event_id(event));
if (Debug) fprintf(stderr,
"\nobject = %X, *event = %X, arg = %X, type = %X\n",
object, event, arg, type);
#endif
if (event_id(event) == SCROLL_REQUEST) {
if ((Scrollbar)arg == vsb) {
#ifdef DEBUG
if (Debug) fprintf(stderr,"arg is vsb, ");
#endif
motion = (Scroll_motion)scrollbar_get(vsb, SCROLL_REQUEST_MOTION);
if (!keyscroll && ((motion == SCROLL_PAGE_FORWARD)
|| (motion == SCROLL_PAGE_BACKWARD))) {
#ifdef DEBUG
if (Debug) fprintf(stderr,"motion is %X (PAGE), ", (int)motion);
#endif
/* now tell bar to undo scroll */
scrollbar_set(vsb, SCROLL_VIEW_START,
scrollbar_get(vsb, SCROLL_LAST_VIEW_START), 0);
if (motion == SCROLL_PAGE_BACKWARD) {
if (current_page-- > 0)
ProcessPage(current_page);
else
current_page++;
}
else {
if (++current_page < totalpages)
ProcessPage(current_page);
else
current_page--;
}
#ifdef DEBUG
if (Debug) fprintf(stderr,"Interposer return (DONE)\n");
#endif
return (NOTIFY_DONE);
}
}
}
#ifdef DEBUG
if (Debug) fprintf(stderr,"calling next func\n");
#endif
retval = (notify_next_event_func(object, event, arg, type));
if (Debug) fprintf(stderr, "Interposer return (%X)\n", retval);
return (retval);
}
/*-->CanvasEventProc*/
void
CanvasEventProc(notused, event)
Canvas notused;
Event *event;
{
static int intval;
#ifdef DEBUG
if (Debug) fprintf(stderr,"event proc called (id = %d) - ",
event_id(event));
#endif
keyscroll = FALSE;
switch (event_id(event)) {
case '\n':
case '\r':
if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER)) {
if ((main_state & SB_MINUSNUMBER)
&& (current_page -= intval) < 0)
current_page = 0;
if ((main_state & SB_PLUSNUMBER)
&& (current_page += intval) >= totalpages)
current_page = totalpages-1;
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
ProcessPage(current_page);
break;
} /* else fall into next page case */
case ' ': /* normal case - start next page */
case 'n':
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
if (++current_page < totalpages)
ProcessPage(current_page);
else
current_page--;
break;
case 'b':
case 'P':
case 'p': /* redisplay from previous page */
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
if (current_page-- > 0)
ProcessPage(current_page);
else
current_page++;
break;
#ifdef KEYBOARDSCROLL
case 'j':
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
keyscroll = TRUE;
scrollbar_scroll_to(vsb, (long)600);
break;
case 'h':
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
keyscroll = TRUE;
scrollbar_scroll_to(hsb, (long)0);
break;
case 'l':
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
keyscroll = TRUE;
scrollbar_scroll_to(hsb, (long)300);
break;
case 'k':
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
keyscroll = TRUE;
scrollbar_scroll_to(vsb, (long)0);
break;
case 'c':
main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
main_state |= SB_INTERPRET;
keyscroll = TRUE;
scrollbar_scroll_to(vsb, (long)RESOLUTION);
scrollbar_scroll_to(hsb, (long)(RESOLUTION/2));
break;
#endif
#ifdef DEBUG
case SCROLL_REQUEST: /* scroll request, after Sb gets it */
{ int a, b, c, d;
if (Debug) {
a = (int)scrollbar_get(vsb, SCROLL_VIEW_START);
b = (int)scrollbar_get(vsb, SCROLL_LAST_VIEW_START);
c = (int)scrollbar_get(hsb, SCROLL_VIEW_START);
d = (int)scrollbar_get(hsb, SCROLL_LAST_VIEW_START);
fprintf(stderr,"\nVsb scroll from %d to %d\n", b, a);
fprintf(stderr,"Hsb scroll from %d to %d\n", d, c);
}
}
break;
#endif
case '-':
/* read in val */
main_state |= SB_MINUSNUMBER;
intval = 0;
break;
case '+':
/* read in val */
main_state |= SB_PLUSNUMBER;
intval = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER))
intval = intval*10 + (event_id(event) - '0');
break;
case '\b':
case 127: /* delete key */
if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER))
intval /= 10;
break;
case MS_RIGHT:
if (event_is_up(event)) break;
#ifdef DEBUG
if (event_meta_is_down(event)) {
(void)menu_show(debugmenu, canvas,
canvas_window_event(canvas, event), 0);
break;
}
#endif
if (event_shift_is_down(event))
(void)menu_show(shiftmenu, canvas,
canvas_window_event(canvas, event), 0);
else
(void)menu_show(menu, canvas,
canvas_window_event(canvas, event), 0);
break;
case MS_LEFT:
canvas_cursor = window_get(canvas, WIN_CURSOR);
if (event_is_up(event)) {
cursor_set(canvas_cursor,
CURSOR_SHOW_CURSOR, TRUE,
CURSOR_SHOW_CROSSHAIRS, FALSE,
0);
}
else {
/*
* All these except the pixrect op
* are defaults but it does not seem
* to work unles they are specified
*/
cursor_set(canvas_cursor,
CURSOR_SHOW_CURSOR, FALSE,
CURSOR_CROSSHAIR_COLOR, 1,
CURSOR_CROSSHAIR_THICKNESS, 1,
CURSOR_CROSSHAIR_GAP, 0,
CURSOR_CROSSHAIR_LENGTH, CURSOR_TO_EDGE,
CURSOR_CROSSHAIR_OP, PIX_SRC|PIX_DST,
CURSOR_SHOW_CROSSHAIRS, TRUE,
0);
}
window_set(canvas, WIN_CURSOR, canvas_cursor, 0);
break;
case WIN_REPAINT:
if (main_state & SB_INITIAL) { /* first time of display */
main_state &= ~SB_INITIAL;
CheckFiles(); /* sets main_state */
OpenDviFile(dviname);
if (main_state & (SB_NOFILE | SB_NODVIFILE))
break;
SetPageMenu();
main_state &= ~SB_NEWFILE;
main_state |= SB_INTERPRET;
ProcessPage(current_page);
}
break;
default:
#ifdef DEBUG
if (Debug) fprintf(stderr,"event proc default case - ");
#endif
}
#ifdef DEBUG
if (Debug) fprintf(stderr,"event proc return\n");
#endif
}
/*
* Now the procedures that actually do the work of
* drawing on the screen. These get called from
* dvistuff to prevent it having to know about
* SunView.
* SetBop just clears the screen and sets the initial
* offset. SetChar and SetRule draw text and lines.
*/
/*-->SetBop*/
void
SetBop()
{
pw_writebackground(pw, 0, 0,
pw->pw_prretained->pr_size.x, pw->pw_prretained->pr_size.y,
PIX_CLR);
/*
* Start with h and v at offset point rather than 0,0.
* This means that offset does not need to be added in
* on every call to SetChar and SetRule.
*/
h = xcanvasoffset * hconv;
v = ycanvasoffset * vconv;
}
/*-->SetChar*/
void
SetChar(charptr, Set)
struct char_entry *charptr;
Boolean Set;
{
hh = PixRound(h, hconv);
vv = PixRound(v, vconv);
if (!charptr->where.isloaded) LoadAChar(charptr);
if (charptr->where.isloaded == TRUE)
pw_rop(pw, hh-charptr->xOffset,
vv-charptr->yOffset,
charptr->width, charptr->height, PIX_SRC | PIX_DST,
charptr->where.address.pixrectptr, 0, 0);
if (Set)
h += charptr->tfmw;
}
/*-->SetRule*/
void
SetRule(a, b, Set)
int a, b;
Boolean Set;
{ /* this routine draws \hrule and \vrule */
int ehh, evv;
hh = PixRound(h, hconv);
vv = PixRound(v-a, vconv);
ehh = PixRound(h + b, hconv);
evv = PixRound(v, vconv);
if (hh == ehh) ehh++;
if (vv == evv) vv--;
if ((a > 0) && (b > 0))
pw_rop(pw, hh, vv,
ehh-hh, evv-vv, PIX_SET, NULL, 0, 0);
if (Set)
h += b;
}
/*
* These next two are only procedures here to avoid
* having dvistuff.c know about Pixwins.
* As they are only called once per page the loss of
* speed is not a problem.
*/
/*-->BatchStart*/
void
BatchStart()
{
pw_batch_on(pw);
}
/*-->BatchEnd*/
void
BatchEnd()
{
pw_batch_off(pw);
}
/*
* Now two procedures that call on things in
* dvistuff to get pages displayed.
*/
/*-->ProcessPage*/
void
ProcessPage(page)
int page;
{
if (DviFileChanged())
RestartDviFile();
SetFrameLabel();
DoPage(page);
}
/*-->RestartDviFile*/
void
RestartDviFile()
{
CloseDviFile();
FreeFontStorage();
main_state &= (~SB_INTERPRET & ~SB_NOFILE);
/* main_state |= SB_NEWFILE; /* to allow a try at open */
CheckFiles(); /* sets main_state */
OpenDviFile(dviname);
if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* something wrong */
return;
SetPageMenu();
main_state &= ~SB_NEWFILE; /* SB_NEWFILE must be set to get to here */
main_state |= SB_INTERPRET;
}
/*
* Now to the menu generating procedures, one for
* each menu. There is also a procedure to set
* the "go to page" menu item depending on the
* number of pages.
* MenuGenerate() deals with most of the interlocking
* to avoid illegal menu choices.
*/
/*-->MenuGenerate*/
Menu
MenuGenerate(object, operation)
Menu object;
Menu_generate operation;
{
if (operation == MENU_CREATE) {
menu_set(menu_get(object, MENU_NTH_ITEM, M_RESTART),
MENU_INACTIVE,
(main_state & (SB_TEXING | SB_NOFILE | SB_NODVIFILE ) ?
TRUE : FALSE),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, M_NEWPAGE),
MENU_INACTIVE,
(main_state & (SB_TEXING | SB_NOFILE | SB_NODVIFILE) ?
TRUE : FALSE),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, M_TEX),
MENU_INACTIVE,
(main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE |
SB_NOTEXFILE) ? TRUE : FALSE),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, M_LATEX),
MENU_INACTIVE,
(main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE |
SB_NOTEXFILE) ? TRUE : FALSE),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, M_EDIT),
MENU_INACTIVE,
(main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE) ?
TRUE : FALSE),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, M_SHELL),
MENU_INACTIVE,
(main_state & (SB_TEXING | SB_EDITING | SB_SHELL) ?
TRUE : FALSE),
0);
}
return (object);
}
/*-->ShiftMenuGenerate*/
Menu
ShiftMenuGenerate(object, operation)
Menu object;
Menu_generate operation;
{
if (operation == MENU_CREATE) {
menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_P & 0xF),
MENU_STRING, (PreLoad ? "reset -p flag" : "set -p flag"),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_B & 0xF),
MENU_STRING, (Batching ? "set -b flag" : "reset -b flag"),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_BIGP & 0xF),
MENU_STRING, (BigPreLoad ? "reset -P flag" : "set -P flag"),
0);
#ifdef USEGLOBALMAG
menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_M & 0xF),
MENU_STRING, (Mflag ? "reset -m flag" : "set -m flag"),
0);
#endif
}
return (object);
}
#ifdef DEBUG
/*-->DebugMenuGenerate*/
Menu
DebugMenuGenerate(object, operation)
Menu object;
Menu_generate operation;
{
if (operation == MENU_CREATE) {
menu_set(menu_get(object, MENU_NTH_ITEM, DM_TOGGLE_D & 0xF),
MENU_STRING, (Debug ? "reset -d flag" : "set -d flag"),
0);
menu_set(menu_get(object, MENU_NTH_ITEM, DM_TOGGLE_X & 0xF),
MENU_STRING, (ExtraDebug ? "reset -x flag" : "set -x flag"),
0);
}
return (object);
}
#endif DEBUG
/*-->SetPageMenu*/
void
SetPageMenu()
{
short i;
if (totalpages > 10)
menu_set(menu,
MENU_REPLACE, 2, longpageitem,
0);
else {
menu_set(menu,
MENU_REPLACE, 2, shortpageitem,
0);
for (i = 0; i < 10; i++)
menu_set(menu_get(tenpagemenu, MENU_NTH_ITEM, i+1, 0),
MENU_INACTIVE, (i < totalpages ? FALSE : TRUE),
0);
}
}
/*
* Now the action procs called after a menu selection
* is made.
*/
/*-->MenuRestart*/
void
MenuRestart(object, item)
Menu object;
Menu_item item;
{
window_release_event_lock(canvas); /* "I may be some time" */
current_page = 0;
RestartDviFile();
DoPage(current_page);
}
/*-->MenuNewPage*/
void
MenuNewPage(object, item)
Menu object;
Menu_item item;
{
panel_set(textinput,
PANEL_LABEL_STRING, "Page number:",
PANEL_VALUE, "",
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(errorheader,
PANEL_SHOW_ITEM, FALSE,
0);
panel_set(errormessage,
PANEL_LABEL_STRING, "",
PANEL_SHOW_ITEM, FALSE,
0);
window_fit(errorpanel);
window_fit(errorframe);
window_set(errorframe,
WIN_X, 100,
WIN_Y, 100,
WIN_SHOW, TRUE,
0);
textinput_state = M_NEWPAGE;
}
/*-->MenuShortPage*/
void
MenuShortPage(object, item)
Menu object;
Menu_item item;
{
current_page = (int)menu_get(item, MENU_VALUE, 0);
current_page--; /* as current_page =0 for page 1 */
if (current_page >= totalpages)
current_page = totalpages - 1;
ProcessPage(current_page);
}
/*-->MenuNewFile*/
void
MenuNewFile(object, item)
Menu object;
Menu_item item;
{
panel_set(textinput,
PANEL_LABEL_STRING, "Filename:",
PANEL_VALUE, "",
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(errorheader,
PANEL_SHOW_ITEM, FALSE,
0);
panel_set(errormessage,
PANEL_LABEL_STRING, "",
PANEL_SHOW_ITEM, FALSE,
0);
window_fit(errorpanel);
window_fit(errorframe);
window_set(errorframe,
WIN_X, 100,
WIN_Y, 100,
WIN_SHOW, TRUE,
0);
textinput_state = M_NEWFILE;
}
/*-->MenuCd*/
void
MenuCd(object, item)
Menu object;
Menu_item item;
{
panel_set(textinput,
PANEL_LABEL_STRING, "Directory:",
PANEL_VALUE, "",
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(errorheader,
PANEL_SHOW_ITEM, FALSE,
0);
panel_set(errormessage,
PANEL_LABEL_STRING, "",
PANEL_SHOW_ITEM, FALSE,
0);
window_fit(errorpanel);
window_fit(errorframe);
window_set(errorframe,
WIN_X, 100,
WIN_Y, 100,
WIN_SHOW, TRUE,
0);
textinput_state = M_CD;
}
/*-->MenuTex*/
void
MenuTex(object, item)
Menu object;
Menu_item item;
{
strcpy(ttyinbuf, "cd ");
strcat(ttyinbuf, getwd(dirbuf));
strcat(ttyinbuf, "\ntex ");
strcat(ttyinbuf, curname);
strcat(ttyinbuf, ".tex\n");
(void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf));
main_state |= SB_TEXING;
window_set(ttyframe, WIN_SHOW, TRUE, 0);
}
/*-->MenuLatex*/
void
MenuLatex(object, item)
Menu object;
Menu_item item;
{
strcpy(ttyinbuf, "cd ");
strcat(ttyinbuf, getwd(dirbuf));
strcat(ttyinbuf, "\nlatex ");
strcat(ttyinbuf, curname);
strcat(ttyinbuf, ".tex\n");
(void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf));
main_state |= SB_TEXING;
window_set(ttyframe, WIN_SHOW, TRUE, 0);
}
/*-->MenuEdit*/
void
MenuEdit(object, item)
Menu object;
Menu_item item;
{
char *tcp;
if ((tcp = getenv("EDITOR")) == NULL)
tcp = "vi";
strcpy(ttyinbuf, tcp);
strcat(ttyinbuf, " ");
strcat(ttyinbuf, getwd(dirbuf));
strcat(ttyinbuf, "/");
strcat(ttyinbuf, curname);
strcat(ttyinbuf, ".tex\n");
(void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf));
main_state |= SB_EDITING;
window_set(ttyframe, WIN_SHOW, TRUE, 0);
}
/*-->MenuShell*/
void
MenuShell(object, item)
Menu object;
Menu_item item;
{
main_state |= SB_SHELL;
window_set(ttyframe, WIN_SHOW, TRUE, 0);
}
/*-->MenuToggleFlag*/
void
MenuToggleFlag(object, item)
Menu object;
Menu_item item;
{
int itemvalue;
itemvalue = (int)menu_get(item, MENU_VALUE, 0);
switch (itemvalue) {
#ifdef DEBUG
case DM_TOGGLE_D:
Debug ^= 1;
break;
case DM_TOGGLE_X:
ExtraDebug ^= 1;
break;
#endif
case SM_TOGGLE_P:
PreLoad ^= 1;
break;
case SM_TOGGLE_B:
Batching ^= 1;
break;
case SM_TOGGLE_BIGP:
BigPreLoad ^= 1;
break;
#ifdef USEGLOBALMAG
case SM_TOGGLE_M:
Mflag ^= 1;
if (Mflag) {
panel_set(textinput,
PANEL_LABEL_STRING, "Magnification:",
PANEL_VALUE, "",
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(errorheader,
PANEL_SHOW_ITEM, FALSE,
0);
panel_set(errormessage,
PANEL_LABEL_STRING, "",
PANEL_SHOW_ITEM, FALSE,
0);
window_fit(errorpanel);
window_fit(errorframe);
window_set(errorframe,
WIN_X, 100,
WIN_Y, 100,
WIN_SHOW, TRUE,
0);
textinput_state = SM_TOGGLE_M;
}
break;
#endif
default:
break;
}
}
/*
* The event proc for the panel which contains the
* error message item and the text input item.
* If the panel event is an ascii one it passes it
* on to the text input item. It removes the panel
* on a left mouse button.
*/
/*-->ErrorEventProc*/
void
ErrorEventProc(object, event)
Panel object;
Event *event;
{
if (event_id(event) <= ASCII_LAST)
panel_accept_key(textinput, event);
else if (event_id(event) == MS_LEFT)
window_set(errorframe,
WIN_SHOW, FALSE,
0);
}
/*
* The notify proc for the panel text input item.
* This gets things like page numbers and filenames
* from the user.
*/
/*-->TextInputProc*/
void
TextInputProc(item, event)
Panel_item item;
Event *event;
{
#ifdef DEBUG
if (Debug)
fprintf(stderr,"TextInputProc(): panel_get_value returns %s\n",
(char *)panel_get_value(textinput));
#endif
strcpy(textinputbuffer, (char *)panel_get_value(textinput));
window_set(errorframe,
WIN_SHOW, FALSE,
0);
if (*textinputbuffer == NULL)
return;
switch(textinput_state) {
case M_NEWPAGE:
sscanf(textinputbuffer, "%d", ¤t_page);
current_page--;
if (current_page >= totalpages)
current_page = totalpages - 1;
ProcessPage(current_page);
break;
case M_NEWFILE:
window_release_event_lock(errorframe);
/* as this may take some time */
SplitFilename(ExpandTilde(textinputbuffer));
/* sets dviname */
CloseDviFile(); /* from dvifp */
FreeFontStorage();
SetBop(); /* clear screen */
current_page = 0;
main_state &= (~SB_INTERPRET & ~SB_NOFILE);
CheckFiles(); /* see what's there */
OpenDviFile(dviname); /* sets dvifp */
SetFrameLabel();
if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* something wrong */
break;
SetPageMenu();
main_state &= ~SB_NEWFILE;
main_state |= SB_INTERPRET;
DoPage(current_page);
break;
case M_CD:
if (chdir(ExpandTilde(textinputbuffer)))
Warning("Couldn't change directory");
SetFrameLabel();
break;
case SM_TOGGLE_M:
user_mag = atoi(textinputbuffer);
break;
default:
break;
}
}
/*
* The done proc for the frame with the tty subwindow.
* It removes the frame and adjusts the display if the
* DVI file has changed.
*/
/*-->FrameDoneProc*/
void
FrameDoneProc(object)
Frame object;
{
int i;
if (Debug) {
fprintf(stderr,
"FrameDoneProc(), object = %X, frame = %X, ttyframe = %X\n",
object, frame, ttyframe);
fprintf(stderr,"calling default done proc for object\n");
}
frame_default_done_proc(object);
main_state &= (~SB_TEXING & ~SB_EDITING & ~SB_SHELL);
CheckFiles(); /* see if anything changed */
if (main_state & SB_NEWFILE) { /* we haven't seen it before */
OpenDviFile(dviname);
if (main_state & SB_NOFILE)/* can't have NODVIFILE as NEWFILE was set */
return;
main_state &= ~SB_NEWFILE;
main_state |= SB_INTERPRET;
DoPage(current_page);
}
else if (DviFileChanged()) {
RestartDviFile();
DoPage(current_page);
}
}
/*
* Now some utility procedures.
*/
/*-->SplitFilename*/
void
SplitFilename(nameptr)
char *nameptr;
{
char *tcp, *tcp1;
Icon temp_icon; /* for changing label */
/* process filename */
tcp = rindex(nameptr, '/');
if (tcp == NULL) {
curarea[0] = '\0';
tcp = nameptr;
}
else {
strncpy(curarea, nameptr, tcp-nameptr+1);
curarea[tcp-nameptr+1] = '\0'; /* as strncpy will not do this */
tcp += 1;
}
tcp1 = index(tcp, '.');
if (tcp1 == NULL) {
strcpy(curname, tcp);
curext[0] = '\0';
}
else {
strncpy(curname, tcp, tcp1-tcp);
strcpy(curext, tcp1);
}
strcpy(dviname, curarea);
strcat(dviname, curname);
if (curext[0] == '\0')
strcat(dviname, ".dvi");
else
strcat(dviname, curext);
#ifdef DEBUG
if (Debug) {
fprintf(stderr,"curarea = %s\n", curarea);
fprintf(stderr,"curname = %s\nsetting icon label to curname\n",
curname);
fprintf(stderr,"curext = %s\n", curext);
fprintf(stderr,"dviname = %s\n", dviname);
}
#endif
temp_icon = (Icon)window_get(frame, FRAME_ICON, 0);
icon_set(temp_icon, ICON_LABEL, curname, 0);
window_set(frame, FRAME_ICON, temp_icon, 0);
}
/*
* CheckFiles tries access on the .dvi file,
* and if that does not exist, on the .tex file
* and sets main_state accordingly.
*/
/*-->CheckFiles*/
void
CheckFiles()
{
char buf[STRSIZE];
if (access(dviname, F_OK | R_OK) == 0) { /* .dvi file present */
if (main_state & SB_NODVIFILE) /* first time .dvi file found */
main_state |= SB_NEWFILE;
main_state &= (~SB_NODVIFILE & ~SB_NOTEXFILE);
}
else {
strcpy(buf, curarea);
strcat(buf, curname);
strcat(buf, ".tex");
if (access(buf, F_OK | R_OK) == 0) { /* no .dvi file but .tex file ok */
main_state |= SB_NODVIFILE;
main_state &= (~SB_NEWFILE & ~SB_NOTEXFILE);
}
else { /* no .tex file either */
main_state |= SB_NODVIFILE | SB_NOTEXFILE;
main_state &= ~SB_NEWFILE;
}
}
}
/*-->ExpandTilde*/
char *
ExpandTilde(iptr)
char *iptr;
{
char buff[STRSIZE];
char *tptr;
struct passwd *passwdptr;
#ifdef DEBUG
if (Debug) fprintf(stderr,"ExpandTilde(%s) - ", iptr);
#endif
if (*iptr == '~') { /* something to do */
strcpy(buff, iptr);
tptr = index(buff, '/');
if ((strlen(buff) == 1) || ((tptr-buff) == 1))
/* expand to our $HOME */
strcpy(iptr, getenv("HOME"));
else { /* ~name/... form */
if (tptr != NULL) *tptr = 0;
if ((passwdptr = getpwnam(&buff[1])) != NULL)
strcpy(iptr, passwdptr->pw_dir);
if (tptr != NULL) *tptr = '/';
}
if (tptr != NULL)
strcat(iptr, tptr); /* complete rest of path if there is any */
}
#ifdef DEBUG
if (Debug) fprintf(stderr,"returns %s\n", iptr);
#endif
return (iptr);
}
/*
* Two error message procedures.
* Warning just displays the message, Error displays
* and then abandons the DVI file and goes to the
* NOFILE state.
*/
/*-->Warning*/
void
Warning(fmt, arg1, arg2, arg3, arg4) /* issue a warning */
char *fmt; /* format */
char *arg1, *arg2, *arg3, *arg4; /* arguments */
{
char message[STRSIZE];
sprintf(message, fmt, arg1, arg2, arg3, arg4);
panel_set(errorheader,
PANEL_LABEL_STRING, "TeXtool Warning:",
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(errormessage,
PANEL_LABEL_STRING, message,
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(textinput,
PANEL_SHOW_ITEM, FALSE,
0);
window_fit(errorpanel);
window_fit(errorframe);
window_set(errorframe,
WIN_X, 100,
WIN_Y, 100,
WIN_SHOW, TRUE,
0);
}
/*-->Fatal*/
void
Fatal(fmt, arg1, arg2, arg3, arg4)/* issue a fatal error message */
char *fmt; /* format */
char *arg1, *arg2, *arg3, *arg4; /* arguments */
{
char message[STRSIZE];
sprintf(message, fmt, arg1, arg2, arg3, arg4);
panel_set(errorheader,
PANEL_LABEL_STRING, "TeXtool Error:",
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(errormessage,
PANEL_LABEL_STRING, message,
PANEL_SHOW_ITEM, TRUE,
0);
panel_set(textinput,
PANEL_SHOW_ITEM, FALSE,
0);
window_fit(errorpanel);
window_fit(errorframe);
window_set(errorframe,
WIN_X, 100,
WIN_Y, 100,
WIN_SHOW, TRUE,
0);
CloseDviFile();
FreeFontStorage(); /* to get to known stable state */
main_state |= SB_NOFILE; /* to stop further processing */
main_state &= (~SB_NEWFILE & ~SB_NODVIFILE & ~SB_NOTEXFILE & ~SB_INTERPRET);
SplitFilename("<no_file>");
SetFrameLabel();
}
#ifdef DEBUG
/*
* A procedure to show the fds we are using.
* There was a leak of fds somewhere where ptys were
* not closed when a frame with a tty subwindow in it
* was destroyed and this was used to find it.
* The tty subframe is now not destroyed but just
* undisplayed to cure the problem.
* It also shows the huge number of fds needed by
* SunView which cuts down on the number available for
* PXL file caching.
*/
/*-->ShowFd*/
void
ShowFd(object, item)
Menu object;
Menu_item item;
{
short i;
struct stat statbuf;
fprintf(stderr,"frame %d, win%d\n",
window_get(frame, WIN_FD), window_get(frame, WIN_DEVICE_NUMBER));
fprintf(stderr,"canvas %d, win%d\n",
window_get(canvas, WIN_FD), window_get(canvas, WIN_DEVICE_NUMBER));
fprintf(stderr,"ttyframe %d, win%d\n",
window_get(ttyframe, WIN_FD), window_get(ttyframe, WIN_DEVICE_NUMBER));
fprintf(stderr,"ttysubwindow %d, win%d\n",
window_get(ttysubwindow, WIN_FD),
window_get(ttysubwindow, WIN_DEVICE_NUMBER));
fprintf(stderr,"errorframe %d, win%d\n",
window_get(errorframe, WIN_FD), window_get(errorframe, WIN_DEVICE_NUMBER));
fprintf(stderr,"errorpanel %d, win%d\n",
window_get(errorpanel, WIN_FD), window_get(errorpanel, WIN_DEVICE_NUMBER));
ShowPxlFd();
for (i=0; i<30; i++) /* enumerate fds */
if (fstat(i,&statbuf) == 0)
fprintf(stderr,"fd %d open, type = %o, inode = %d\n",
i,
statbuf.st_mode & S_IFMT,
statbuf.st_ino);
}
#endif